﻿package de.gameduell.framework.application.controller {
	import de.gameduell.framework.application.Settings;
	import de.gameduell.framework.application.event.GameEvent;
	import de.gameduell.framework.application.protocol.Protocol;
	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.error.ErrorManager;
	import de.gameduell.framework.error.GDErrorEvent;
	import de.gameduell.framework.game.cheat.CheatDetection;
	import de.gameduell.framework.util.FlashVars;
	import de.gameduell.framework.util.HashMap;
	import de.gameduell.net.src.communication.CommunicationEvent;
	import de.gameduell.net.src.communication.ICommunication;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.system.Capabilities;	

	public class Controller extends EventDispatcher implements IController{

		private const MAX_LOG_MESSAGES:int = 2;

		protected var communication:ICommunication;
		protected var _slotid:int;
		protected var _abortedByUser:Boolean = false;
		protected var _reconnecting:Boolean  = false;
		
		private var loggingEnabled:Boolean   = true;
		private var dumpErrorToServer:Boolean = true;
		private var logCount:int = 0;
		
		protected var _cheatDetection:CheatDetection;
		protected var _isStandalone:Boolean;
		protected var errorManager:ErrorManager;
		protected var settings:Settings;
		private var _tipsEnabled:Boolean;
		
		public function Controller() {
			_isStandalone = false;
			errorManager = ErrorManager.getInstance();
			errorManager.addEventListener(GDErrorEvent.ERROR, onError);
			_tipsEnabled = FlashVars.getKeyValue("GameCount") == "0";
		}
		
		private function onError(event:GDErrorEvent):void {
			sendError(event.error.type,event.error.message);
		}

		public function setCommunication(aCommunication:ICommunication):void{
			communication = aCommunication;
			communication.addEventListener(CommunicationEvent.RECONNECT, onReconnect);
			communication.addEventListener(CommunicationEvent.RECONNECTED, onReconnected);
		}

		public function setSettings(aSettings:Settings):void {
			settings = aSettings;
			dumpErrorToServer = settings.dumpErrorToServer;
		}

		public function setCheatDetection(aCheatDetection:CheatDetection):void {
			_cheatDetection = aCheatDetection;
		}
		
		public function get cheatDetection():CheatDetection {
			return _cheatDetection;
		}

		protected function onReconnect(event:CommunicationEvent):void {
			_reconnecting = true;
			dispatchEvent(new CommunicationEvent(CommunicationEvent.RECONNECT));
		}
		
		protected function onReconnected(event:CommunicationEvent):void {
			_reconnecting = false;
			dispatchEvent(new CommunicationEvent(CommunicationEvent.RECONNECTED));
		}
		
		public function get tipsEnabled():Boolean {
			return _tipsEnabled;
		}

		public function get isReconnecting():Boolean {
			return _reconnecting;
		}
		
		public function set isStandalone(standalone:Boolean):void {
			_isStandalone = standalone;
		}

		public function get isStandalone():Boolean{
			return _isStandalone;
		}

		public function set tipsEnabled(isEnabled:Boolean):void {
			if(_tipsEnabled != isEnabled){
				_tipsEnabled = isEnabled;
				dispatchEvent(new GameEvent(GameEvent.TIPS_ENABLE_CHANGED));
			}
		}

		public function set slotid(id:int):void {
			_slotid = id;
		}
		
		public function get slotid():int {
			return _slotid;
		}
		
		public function sendAbort():void{
			abortedByUser = true;
			communication.send(Protocol.ABORT, [_slotid]);
		}
		
		public function sendError(errorCode:String, dump:String = "noinfo"):void {
			if(dumpErrorToServer){
				if(loggingEnabled){
					var debug:String = String(Capabilities.isDebugger);
					var screenRes:String = Capabilities.screenResolutionX + ":" + Capabilities.screenResolutionY;
					var ver:String = Capabilities.version;
					var manufact:String = Capabilities.manufacturer;
					var os:String = Capabilities.os;
				
					Debug.trace("Controller::sendError: " + errorCode + ":" + dump, Debug.ERROR);
					communication.send(Protocol.ERROR, [os, ver, screenRes + "::" + debug + "::" + manufact + "::" + errorCode + "::" + dump]);
				}
				loggingEnabled = logCount++ < MAX_LOG_MESSAGES;
			}
		}
		
		/**
		 * called at the very end of the game,
		 * redirects user to the results page
		 */
		public function exit(event:Event = null):void {
			var sendScoreSet:Boolean = false;
			try{
				sendScoreSet = settings.sendScore && settings.sendScoreURL != null;
			}catch (e:Error) {
          		Debug.trace("Controller::exit() - loader contains old settings class: dumpScore() not available", Debug.WARNING);
            }
            
            if (FlashVars.getKeyValue("durl") != FlashVars.NO_VALUE){
				try {
					if(sendScoreSet){
						navigateToURL(new URLRequest(unescape(FlashVars.getKeyValue("durl"))+"&"+FlashVars.ENCRYPTED_SCORE+"="+FlashVars.getKeyValue(FlashVars.ENCRYPTED_SCORE)), "_self");
					}else{
						if(FlashVars.getKeyValue("attachscore") == "true"){
							navigateToURL(new URLRequest(FlashVars.getKeyValue("durl") + "&score=" + FlashVars.getKeyValue("gameScore")), "_self");
						}else {
							navigateToURL(new URLRequest(FlashVars.getKeyValue("durl")), "_self");
						}
					}
				}
	            catch (er:Error) {
					Debug.trace("Controller::leaveGame: unable to reidirect -> error: " + er, Debug.ERROR);
				}
            }
		}
		
		protected function set abortedByUser(aborted:Boolean):void {
			_abortedByUser = aborted;
		}
		
		protected function get abortedByUser():Boolean {
			return _abortedByUser;
		}
	}
}